﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using Raw1.DTOs;


namespace Raw1
{
    public class FileSystemMonitor : Monitor
    {

#region Private members
        private string _path = @"C:\Watch";
        private FileSystemWatcher _fileWatcher;
#endregion

#region Public members
        public override Monitors MonitorType { get; set; }
        public override event EventHandler MonitorChangedEvent;
        public String Path 
        { 
            get 
            { 
                return _path; 
            } 
        }
        public List<FileSystemDTO> Files
        {
            get
            {
                List<FileSystemDTO> _files = new List<FileSystemDTO>();
                foreach (string path in Directory.GetFiles(_path))
                {
                    var info = new FileInfo(path);
                    FileSystemDTO _dto = new FileSystemDTO();
                    _dto.Created = info.CreationTime;
                    _dto.Directory = info.DirectoryName;
                    _dto.FileName = info.Name;
                    _dto.Modified = info.LastWriteTime;
                    _files.Add(_dto);
                }
                return _files;
            }
            
        }

#endregion

#region constructor

        public FileSystemMonitor()
        {
            _fileWatcher = new FileSystemWatcher();
        }

#endregion

#region Public Methods
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public override void RunWatcher()
        {
            _fileWatcher.Path = _path;

            // Begin watching.
            _fileWatcher.EnableRaisingEvents = true;


            //fileSystemWatcher1.SynchronizingObject = this;

            // Only watch text files.
            _fileWatcher.Filter = "*.txt";

            /* Watch for changes in CreationTime, DirectoryName, FileName, LastWrite, size and the renaming of files or directories. */
            _fileWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size;

            // Add event handlers.
            _fileWatcher.Changed += new FileSystemEventHandler(OnChanged);
            _fileWatcher.Created += new FileSystemEventHandler(OnCreated);
            _fileWatcher.Deleted += new FileSystemEventHandler(OnDeleted);
            _fileWatcher.Renamed += new RenamedEventHandler(OnRenamed);
            _fileWatcher.Disposed += new EventHandler(OnDisposed);
            _fileWatcher.Error += new ErrorEventHandler(OnError);
        }

        public void ReadConfiguration()
        {
            _path = Properties.Settings.Default.FileSystem;
        }
#endregion

#region Private Methods
        private void OnChanged(object sender, FileSystemEventArgs e)
        {
            // Occurs when the contents of the file change.
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {
                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                args.ChangeType = e.ChangeType;
                args.FileSystemArgs = e;
                args.FullPath = e.FullPath;
                args.Name = e.Name;

                handler(this, args);
            }

        }
        private void OnCreated(object sender, FileSystemEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of 
            // a race condition if the last subscriber unsubscribes 
            // immediately after the null check and before the event is raised.
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {
                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                args.ChangeType = e.ChangeType;
                args.FileSystemArgs = e;
                args.FullPath = e.FullPath;
                args.Name = e.Name;

                handler(this, args);
            }
        }
        private void OnDeleted(object sender, FileSystemEventArgs e)
        {
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {
                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                args.ChangeType = e.ChangeType;
                args.FileSystemArgs = e;
                args.FullPath = e.FullPath;
                args.Name = e.Name;

                handler(this, args);
            }
        }
        private void OnRenamed(object sender, RenamedEventArgs e)
        {
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {
                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                args.ChangeType = e.ChangeType;
                args.FileSystemArgs = e;
                args.FullPath = e.FullPath;
                args.Name = e.Name;

                handler(this, args);
            }
        }
        private void OnDisposed(object sender, EventArgs e)
        {
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {
                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                //args.ChangeType = e.ChangeType;
                //args.FileSystemArgs = e;
                //args.FullPath = e.FullPath;
                //args.Name = e.Name;

                handler(this, args);
            }
        }
        private void OnError(object sender, ErrorEventArgs e)
        {
            EventHandler handler = MonitorChangedEvent;
            if (handler != null)
            {

                FileSystemMonitorArgs args = new FileSystemMonitorArgs(this);
                //args.ChangeType = e.ChangeType;
                //args.FileSystemArgs = e;
                //args.FullPath = e.FullPath;
                //args.Name = e.Name;

                handler(this, args);
            }
        }
#endregion
        
    }
}
